package org.weasel.views;

import java.util.Arrays;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.weasel.business.Task;
import org.weasel.controllers.TaskListController;
import org.weasel.models.ITaskListViewer;
import org.weasel.models.TaskList;

public class TaskListComposite extends Composite {
	private Table table;
	private TableViewer tableViewer;
	  //  @jve:decl-index=0:
	private TaskListController controller;  //  @jve:decl-index=0:

	// Set the table column property names
	private final String COMPLETED_COLUMN 		= "completed";
	private final String DESCRIPTION_COLUMN 	= "description";

	// Set column names
	private String[] columnNames = new String[] { 
			COMPLETED_COLUMN, 
			DESCRIPTION_COLUMN,
			};
	
	public TaskListComposite(Composite parent, int style, TaskListController controller) {
		super(parent, style);
		this.controller = controller;
		initialize();
	}
	
	public void setController(TaskListController controller){
		this.controller = controller;
	}
	
	public TableViewer getViewer(){
		return this.tableViewer;
	}

	private void initialize() {
		setSize(new Point(300, 200));
		setLayout(new GridLayout());
		addChildControls(this);
	}
	
	private void addChildControls(Composite composite) {
		// Create a composite to hold the children
		GridData gridData = new GridData (GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_BOTH);
		composite.setLayoutData (gridData);

		// Set numColumns to 3 for the buttons 
		GridLayout layout = new GridLayout(3, false);
		layout.marginWidth = 4;
		composite.setLayout (layout);

		// Create the table 
		createTable(composite);
		
		// Create and setup the TableViewer
		createTableViewer();
		tableViewer.setContentProvider(new ViewContentProvider());
		tableViewer.setLabelProvider(new ViewLabelProvider());
//		tableViewer.setInput(taskList);

		// Add the buttons
		createButtons(composite);
	}

	/**
	 * Create the Table
	 */
	private void createTable(Composite parent) {
		int style = SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | 
					SWT.FULL_SELECTION | SWT.HIDE_SELECTION;

//		final int NUMBER_COLUMNS = 2;

		table = new Table(parent, style);
		
		GridData gridData = new GridData(GridData.FILL_BOTH);
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalSpan = 3;
		table.setLayoutData(gridData);		
					
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		// 1st column with image/checkboxes - NOTE: The SWT.CENTER has no effect!!
		TableColumn column = new TableColumn(table, SWT.CENTER, 0);		
		column.setText("!");
		column.setWidth(20);
		
		// 2nd column with task Description
		column = new TableColumn(table, SWT.LEFT, 1);
		column.setText("Description");
		column.setWidth(400);
		// Add listener to column so tasks are sorted by description when clicked 
		column.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
//				tableViewer.setSorter(new ExampleTaskSorter(ExampleTaskSorter.DESCRIPTION));
			}
		});
	}

	/**
	 * Create the TableViewer 
	 */
	private void createTableViewer() {

		tableViewer = new TableViewer(table);
		tableViewer.setUseHashlookup(true);
		
		tableViewer.setColumnProperties(columnNames);

		// Create the cell editors
		CellEditor[] editors = new CellEditor[columnNames.length];

		// Column 1 : Completed (Checkbox)
		editors[0] = new CheckboxCellEditor(table);

		// Column 2 : Description (Free text)
		TextCellEditor textEditor = new TextCellEditor(table);
		((Text) textEditor.getControl()).setTextLimit(120);
		editors[1] = textEditor;


		// Assign the cell editors to the viewer 
		tableViewer.setCellEditors(editors);
		// Set the cell modifier for the viewer
		tableViewer.setCellModifier(new CellModifier(this));
		// Set the default sorter for the viewer 
//		tableViewer.setSorter(new ExampleTaskSorter(ExampleTaskSorter.DESCRIPTION));
	}
	
	/**
	 * Add the "Add", "Delete" and "Close" buttons
	 * @param parent the parent composite
	 */
	private void createButtons(Composite parent) {
		// Create and configure the "Add" button
		Button add = new Button(parent, SWT.PUSH | SWT.CENTER);
		add.setText("Add");
		
		GridData gridData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
		gridData.widthHint = 80;
		add.setLayoutData(gridData);
		add.addSelectionListener(new SelectionAdapter() {
      		// Add a task to the ExampleTaskList and refresh the view
			public void widgetSelected(SelectionEvent e) {
				controller.addTask();
			}
		});

		//	Create and configure the "Delete" button
		Button delete = new Button(parent, SWT.PUSH | SWT.CENTER);
		delete.setText("Delete");
		gridData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
		gridData.widthHint = 80; 
		delete.setLayoutData(gridData); 

		delete.addSelectionListener(new SelectionAdapter() {
			//	Remove the selection and refresh the view
			public void widgetSelected(SelectionEvent e) {
				Task task = (Task) ((IStructuredSelection)tableViewer.getSelection()).getFirstElement();
				if (task != null) {
					controller.removeTask(task);
				}
			}
		});	
	}
	
	/**
	 * Return the column names in a collection
	 * 
	 * @return List  containing column names
	 */
	public java.util.List getColumnNames() {
		return Arrays.asList(columnNames);
	}
	
	
	/**
	 * Inner classes
	 *
	 */
	
	class ViewContentProvider implements IStructuredContentProvider, ITaskListViewer {
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
			if (newInput != null)
				((TaskList) newInput).addChangeListener(this);
			if (oldInput != null)
				((TaskList) oldInput).removeChangeListener(this);
		}

		public void dispose() {
			controller.getTaskList().removeChangeListener(this);
		}

		public Object[] getElements(Object parent) {
			//object is of type UserStory
			return controller.getTaskList().getTasks().toArray();
		}

		public void addTask(Task task) {
			tableViewer.add(task);
		}

		public void removeTask(Task task) {
			tableViewer.remove(task);		
		}

		public void updateTask(Task task) {
			tableViewer.update(task, null);
		}
	}
	
	class ViewLabelProvider extends LabelProvider implements
			ITableLabelProvider {

		private Image getImage(boolean isSelected) {
			if(isSelected)
				return new Image(Display.getCurrent(), getClass().getResourceAsStream("/icons/checked.gif"));
			else
				return new Image(Display.getCurrent(), getClass().getResourceAsStream("/icons/unchecked.gif"));
		}

		/**
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
		 *      int)
		 */
		public String getColumnText(Object element, int columnIndex) {
			String result = "";
			Task task = (Task) element;
			switch (columnIndex) {
			case 0: // COMPLETED_COLUMN
				break;
			case 1:
				result = task.getDescription();
				break;
			default:
				break;
			}
			return result;
		}

		/**
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
		 *      int)
		 */
		public Image getColumnImage(Object element, int columnIndex) {
			if(columnIndex == 0){
				return getImage(((Task)element).isComplete());
			}else
				return null;
		}
	}
	
	class CellModifier implements ICellModifier {
		private TaskListComposite taskListComposite;
		@SuppressWarnings("unused")
		private String[] columnNames;
		
		/**
		 * Constructor 
		 * @param TableViewerExample an instance of a TableViewerExample 
		 */
		public CellModifier(TaskListComposite taskListComposite) {
			super();
			this.taskListComposite = taskListComposite;
		}

		/**
		 * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String)
		 */
		public boolean canModify(Object element, String property) {
			return true;
		}

		/**
		 * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String)
		 */
		public Object getValue(Object element, String property) {

			// Find the index of the column
			int columnIndex = taskListComposite.getColumnNames().indexOf(property);

			Object result = null;
			Task task = (Task) element;

			switch (columnIndex) {
				case 0 : // COMPLETED_COLUMN 
					result = new Boolean(task.isComplete());
					break;
				case 1 : // DESCRIPTION_COLUMN 
					result = task.getDescription();
					break;
				default :
					result = "";
			}
			return result;	
		}

		/**
		 * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, java.lang.Object)
		 */
		public void modify(Object element, String property, Object value) {	

			// Find the index of the column 
			int columnIndex	= taskListComposite.getColumnNames().indexOf(property);
				
			TableItem item = (TableItem) element;
			Task task = (Task) item.getData();
			String valueString;

			switch (columnIndex) {
				case 0 : // COMPLETED_COLUMN 
				    task.setComplete(((Boolean) value).booleanValue());
					break;
				case 1 : // DESCRIPTION_COLUMN 
					valueString = ((String) value).trim();
					task.setDescription(valueString);
					break;
				default :
			}
			
			controller.taskChanged(task);
		}
	}

}
